<?php
/**
 * Created by PhpStorm.
 * User: xtliy
 * Date: 2018/4/24
 * Time: 16:52
 */

namespace Liyq\ApiDocs\Console;


use Illuminate\Console\Command;
use Illuminate\Support\Facades\Route;
use phpDocumentor\Reflection\DocBlock;
use ReflectionClass;
use Liyq\ApiDocs\Generators\LaravelGenerators;

class GenerateDocumentation extends Command
{
    protected $signature = 'api:generate
                            {--output=public/apidocs : 文档输出的路径}
                            {--routePrefix=api/* : 生成api文档的路由前缀}
    ';

    protected $description = '根据路由生成api文档';

    public function handle() {
        $generator = new LaravelGenerators();

        $parsedRoutes = $this->processRouters($generator);

        $parsedRoutes = collect($parsedRoutes)->groupBy('resource')->sort(function ($a, $b) {
            return strnatcmp($a->first()['resource'], $b->first()['resource']);
        });

        $this->render($parsedRoutes);
    }

    private function render($routes) {
        $outputPath = $this->option('output');

        $doc = view('apidocs::document')
            ->with('url', config('url'))
            ->with('routes', $routes);

        $this->create($outputPath);
        //输出html
        file_put_contents($outputPath . "/index.html", $doc);
    }

    private function processRouters(LaravelGenerators $generate, $routePrefix = 'api/*') {
        $routers = Route::getRoutes();
        $parsedRouters = [];
        foreach ($routers as $route) {
            if (str_is($routePrefix, $generate->getUri($route))) {
                if ($this->isValidRoute($route) && $this->isRouterVisibleForDocumentation($route->getAction()['uses'])) {
                    $parsedRouters[] = $generate->processRoute($route);
                }
            }
        }

        return $parsedRouters;
    }

    private function isValidRoute($route) {
        return !is_callable($route->getAction()['uses']) && !is_null($route->getAction()['uses']);
    }

    private function isRouterVisibleForDocumentation($route) {
        list ($class, $method) = explode('@', $route);
        $reflection = new ReflectionClass($class);
        $comment = $reflection->getMethod($method)->getDocComment();
        if ($comment) {
            $phpdoc = new DocBlock();

            return collect($phpdoc->getTags())->filter(function ($tag) use ($route) {
                return $tag->getName() === 'hideFormAPIDocumentation';
            })->isEmpty();
        }

        return true;
    }


    private function create($folder) {
        if (!is_dir($folder)) {
            mkdir($folder, 0777, true);
            mkdir($folder . '/css');
        }

        copy(__DIR__ . '/../../resources/stubs/css/style.css', $folder . '/css/style.css');
        rcopy(__DIR__ . '/../../resources/stubs/css/imgs/', $folder . '/css/imgs');
        rcopy(__DIR__ . '/../../resources/stubs/css/fonts/', $folder . '/css/fonts');
    }


}